/**
 * @file singletonapp.c
 * @brief Sorgente per l'implementazione dell'entità singleton di gestione delle risorse applicative.
 *
 * In questo file sono implementate le funzioni private di gestione concorrenziale delle risorse e la funzione pubblicha
 * di richiesta delle risorse.
 * In attinenza alle risorse applicative vengono qui definite anche le funzioni di utilità che servono per confrontare
 * Comandi e Richieste.
 *
 * @date Mar 3, 2012
 * @author Francesco Corvino
 */
#include "singletonapp.h"

/**
 * \brief inizializzazione privata del singleton.
 */
static SingletonApp singleton;
static int _singletonApp_status = 0;

/**
 * \brief inizializzazione del singleton
 */
void SingleApp_initialize(DescApplication * initvalue){
	if(_singletonApp_status==0) { // eseguibile solo una volta
		memcpy(&singleton.resource,initvalue,sizeof(DescApplication));
		int res = pthread_mutex_init(&singleton.contrSing,NULL);
		if(res!=-1) _singletonApp_status++;
	}
}

void _singleApp_wait(){
	if(_singletonApp_status==0) {
		int res = pthread_mutex_init(&singleton.contrSing,NULL);
		if(res!=-1) _singletonApp_status++;
	}
	pthread_mutex_lock(&singleton.contrSing);
}

void _singleApp_free(){
	pthread_mutex_unlock(&singleton.contrSing);
}

int SingleApp_getResource(SingApp_OperationCunc operation){
	_singleApp_wait();
	int res = (*operation)(&singleton.resource);
	_singleApp_free();
	return res;
}


/** \brief Funzione utilizzata per confrontrare due Comandi per nome.
 *
 */
int SingApp_CMDSelector(const void * a, const void * b){
	if(a==NULL && b==NULL) return 0;
	if(a==NULL) return 1;
	if(b==NULL) return -1;
	DescCommand * cmdA = (DescCommand*) a;
	DescCommand * cmdB = (DescCommand*) b;
	return strcmp(cmdA->name, cmdB->name);
}

/** \brief Funzione utilizzata per confrontare due richieste dell'utente in base al comando.
 * Solitamente non utilizzata
 */
int SingApp_ReqSelectorByNameCMD(const void * a, const void * b){
	if(a==NULL && b==NULL) return 0;
	if(a==NULL) return 1;
	if(b==NULL) return -1;
	DescRequest * reqA = (DescRequest*) a;
	DescRequest * reqB = (DescRequest*) b;
	return strcmp(reqA->nameCmd,reqB->nameCmd);
}


